package com.yxy.handler;

import cn.hutool.json.JSONObject;
import com.yxy.properties.JwtProperties;
import com.yxy.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;

import java.io.IOException;
import java.net.URI;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * websocket处理类
 */
@ServerEndpoint("/ws")
@Slf4j
public class WebSocketServerHandler implements WebSocketHandler {

    private static JwtProperties jwtProperties = null;

    public WebSocketServerHandler(JwtProperties jwtProperties) {
        this.jwtProperties = jwtProperties;
    }

    // 存放用户登录信息
    private static final Map<Integer, SessionUserInfo> userInfoMap = new HashMap<>();

    static class SessionUserInfo {
        WebSocketSession session;
        LocalDateTime loginTime;

        SessionUserInfo(WebSocketSession session, LocalDateTime loginTime) {
            this.session = session;
            this.loginTime = loginTime;
        }
    }

    private static final String DUPLICATE_LOGIN = "DUPLICATE_LOGIN";

    /**
     * 连接建立成功后调用
     *
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        log.info("连接成功");
    }

    /**
     * 接收到消息时调用
     *
     * @param session
     * @param message
     * @throws Exception
     */
    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        log.info("收到消息：{}", message);
        String payload = (String) message.getPayload();
        // 反序列化
        JSONObject jsonObject = new JSONObject(payload);
        String type = jsonObject.getStr("type");
        switch (type) {
            case "LOGIN":
                handleLogin(session, jsonObject);
                break;
            case "LOGOUT":
                handleLogout(jsonObject);
                break;
        }

    }

    /**
     * 错误时调用
     *
     * @param session
     * @param exception
     * @throws Exception
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        System.out.println("错误：" + exception.getMessage());
    }

    /**
     * 连接关闭后调用
     *
     * @param session
     * @param closeStatus
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        log.info("连接关闭");
        Iterator<Map.Entry<Integer, SessionUserInfo>> iterator = userInfoMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Integer, SessionUserInfo> entry = iterator.next();
            SessionUserInfo info = entry.getValue();
            if (info.session == session) {
                iterator.remove();
                log.info("用户{}退出登录", entry.getKey());
                break;
            }
        }
    }

    /**
     * 是否支持部分消息
     *
     * @return
     */
    @Override
    public boolean supportsPartialMessages() {
        return false;
    }

    /**
     * 登录处理
     *
     * @param session
     * @throws IOException
     */
    public static void handleLogin(WebSocketSession session, JSONObject jsonObject) throws IOException {
        String token = jsonObject.getStr("token");
        Claims claims = JwtUtil.parseJwt(jwtProperties.getUserSecretKey(), token);
        Integer uId = Integer.valueOf(claims.get("u_id").toString());
        // 判断用户是否登录过
        if (userInfoMap.containsKey(uId)) {
            // 判断时间的先后顺序
            // 获取原始用户信息
            SessionUserInfo sessionUserInfo = userInfoMap.get(uId);
            if (sessionUserInfo.loginTime.isBefore(LocalDateTime.now())) {
                JSONObject msgObject = new JSONObject();
                msgObject.put("type", DUPLICATE_LOGIN);
                sessionUserInfo.session.sendMessage(new TextMessage(msgObject.toString()));
            }
        }
        // 添加用户登录信息
        userInfoMap.put(uId, new SessionUserInfo(session, LocalDateTime.now()));
    }

    /**
     * 登出处理
     * @param jsonObject
     * @throws IOException
     */
    public static void handleLogout(JSONObject jsonObject) throws IOException {
        Integer userId = Integer.valueOf(jsonObject.getStr("userId"));
        SessionUserInfo sessionUserInfo = userInfoMap.get(userId);
        if (sessionUserInfo != null) {
            sessionUserInfo.session.close();
        }
    }

    /**
     * 获取token信息
     * 开始用路径携带参数，改为从接收的消息中获取
     */
//    public static String getToken(WebSocketSession session) {
//        String token = null;
//        URI uri = session.getUri();
//        String query = uri.getQuery(); // 获取查询参数
//        Map<String, String> queryMap = new HashMap<>();
//        if (query != null) {
//            String[] pairs = query.split("&");
//            for (String pair : pairs) {
//                int idx = pair.indexOf("=");
//                if (idx != -1) {
//                    // 例如 id = 1
//                    // pair.substring(0, idx) -> id
//                    // pair.substring(idx + 1) -> 1
//                    // 左闭右开
//                    queryMap.put(pair.substring(0, idx), pair.substring(idx + 1));
//                }
//            }
//            token = queryMap.get("token");
//        }
//        return token;
//    }
}
